/*
 * Copyright 2011 Clean GWT
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.cleanform.gwt.chinesechess.server.comet;

import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import com.cleanform.gwt.chinesechess.shared.comet.UserEvent;

/**
 * The manager to manage comet clients.
 * 
 * @author Jess
 * @version 1.0
 * @since 1.0
 */
public class CometManager {
	private static CometManager instance;

	public static CometManager getInstance() {
		if (instance == null) {
			instance = new CometManager();
		}
		return instance;
	}

	private Map<String, CometEventPool> clientPools = new Hashtable<String, CometEventPool>();

	private CometManager() {
	}

	/**
	 * Adds a client.
	 * 
	 * @param clientid the clientid
	 */
	public void addClient(String clientid) {
		clientPools.put(clientid, new CometEventPool());
	}

	/**
	 * Adds a comet event for a client.
	 * 
	 * @param clientid the clientid
	 * @param event the event
	 */
	public void addCometEvent(String clientid, UserEvent event) {
		CometEventPool pool = clientPools.get(clientid);
		if (pool == null) {
			return;
		}
		synchronized (pool) {
			pool.addEvent(event);
			pool.notifyAll();
		}
	}

	/**
	 * Broadcast event to all clients.
	 * 
	 * @param event the event
	 */
	public void broadcast(UserEvent event) {
		for (String clientid : clientPools.keySet()) {
			addCometEvent(clientid, event);
		}
	}

	/**
	 * Broadcast event to all clients and exclude one.
	 * 
	 * @param event the event
	 * @param exclude the exclude one
	 */
	public void broadcast(UserEvent event, String exclude) {
		for (String clientid : clientPools.keySet()) {
			if (clientid.equals(exclude)) {
				continue;
			}
			addCometEvent(clientid, event);
		}
	}

	/**
	 * Gets all clients.
	 * 
	 * @return all the clients
	 */
	public Collection<String> getClients() {
		return clientPools.keySet();
	}

	public List<UserEvent> getCometEvents(String clientid) {
		CometEventPool pool = clientPools.get(clientid);
		if (pool == null) {
			return null;
		}
		synchronized (pool) {
			if (!pool.hasEvents()) {
				try {
					pool.wait(30000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			return pool.pollEvents();
		}
	}

	/**
	 * Checks whether client is in the client pools.
	 * 
	 * @param clientid the client id
	 * @return whether client is in the client pools
	 */
	public boolean hasClient(String clientid) {
		return clientPools.containsKey(clientid);
	}

	/**
	 * Removes a client.
	 * 
	 * @param clientid the clientid
	 */
	public void removeClient(String clientid) {
		clientPools.remove(clientid);
	}
}
